package cn.jsj.invite.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.jsj.invite.dao.MailDao;
import cn.jsj.invite.interceptor.SimpleMailFactory;
import cn.jsj.invite.service.EmailService;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class EmailServiceImpl implements EmailService {


    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    @Autowired
    private MailDao mailDao;

    @Autowired
    private SimpleMailFactory simpleMailFactory;


    /**
     * 发送一个邮件（控制好频率，发送邮件太频繁不行）
     *
     * @param title      邮件标题
     * @param content    邮件内容
     * @param aimAddress 发送地址
     * @return 邮件发送耗费时间（毫秒）
     */
    @Override
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public Long pushMailMessage(String title, String content, String aimAddress) {
        long startTime = System.currentTimeMillis();
        aimAddress = aimAddress.trim();
        // 检查提供的邮件地址是否在黑名单中
        Boolean isInBlackList = mailDao.addressIsInBlackList(aimAddress);
        if (Boolean.FALSE.equals(isInBlackList)) {
            try {
                SimpleMailMessage message = simpleMailFactory.getSimpleMailMessage(aimAddress, content, title);
                javaMailSender.send(message);
            } catch (MailException e) {
                e.printStackTrace();

                // 捕获到异常，将非法的邮件地址保存在黑名单中
                mailDao.insertBlackAddress(aimAddress);
            }
        } else {
            log.info("黑名单内的邮件地址：{}", aimAddress);
        }
        return System.currentTimeMillis() - startTime;
    }

    /**
     * 生成6位验证码并发送到目标邮箱
     *
     * @param durationTime 验证码有效时间，单位毫秒
     * @param aimAddress   目标邮件地址
     * @return 验证码
     */
    @Override
    public String sendVerificationCode(long durationTime, String aimAddress, HttpServletRequest request) {
        String verificationCode = RandomUtil.randomNumbers(6);
        aimAddress = aimAddress.trim();
        log.info("验证码：{} 邮箱地址：{}", verificationCode, aimAddress);
        pushMailMessage("验证码：" + verificationCode, "本次验证码为：" + verificationCode + "请及时填写。", aimAddress);
        redisTemplate.opsForValue().set(aimAddress, verificationCode, durationTime, TimeUnit.MILLISECONDS);
        return verificationCode;
    }

    /**
     * 检查验证码是否有效
     *
     * @param verificationCode 验证码
     * @param email            邮箱地址
     * @return true正确，保证不返回null
     */
    @Override
    public Boolean checkVerificationCode(String verificationCode, String email) {
        if (verificationCode == null || StringUtils.isBlank(verificationCode.trim())) {
            return false;
        }
        email = email.trim();
        Serializable result = redisTemplate.opsForValue().get(email);
        redisTemplate.delete(email);
        if (result == null) {
            return false;
        }
        String checkCode = result.toString();
        log.info("验证码:{}", checkCode);
        return checkCode.equalsIgnoreCase(verificationCode);
    }
}
